package org.jdsm.flow.core.utils.impl.objectify;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import org.jdsm.flow.core.base.dao.IGenericDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * User: mikom
 * Date: 3/11/13
 * Time: 1:58 PM
 */
public abstract class GenericDao<T> implements IGenericDao<T, Long> {

    private static final Logger log = LoggerFactory.getLogger(GenericDao.class);
    @Resource
    private ObjectifyFactory objectifyFactory;

    private Class<T> type;

    public GenericDao() {
        Type t = getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) t;
        type = (Class<T>) pt.getActualTypeArguments()[0];
    }

    private Objectify ofy() {
        return objectifyFactory.begin();
    }

    @Override
    public T save(T t) {
        return update(t);
    }

    @Override
    public T find(Long id) {
        T entity = ofy().load().type(type).id(id).get();
        log.debug("found entity : {} by id: {}", entity, id);
        return entity;
    }

    @Override
    public void delete(Long id) {
        T entity = ofy().load().type(type).id(id).get();
        if (entity == null) {
            log.warn("can't find entity by id:{} for type:{}", id, type);
            return;
        }
        ofy().delete().entity(entity);
        log.debug("entity : {} was deleted by id: {}");
    }

    @Override
    public T update(T t) {
        Key<T> entityKey = ofy().save().entity(t).now();
        T entity = ofy().load().key(entityKey).get();
        log.debug("entity {} was saved or updated", entity);
        return entity;
    }

    public ObjectifyFactory getObjectifyFactory() {
        return objectifyFactory;
    }

    public void setObjectifyFactory(ObjectifyFactory objectifyFactory) {
        this.objectifyFactory = objectifyFactory;
    }
}
